package lion.json;

import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.output.StringBuilderWriter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import lion.json.handlers.ArrayHandler;
import lion.json.handlers.BooleanHandler;
import lion.json.handlers.ByteArrayHandler;
import lion.json.handlers.ClassHandler;
import lion.json.handlers.CollectionHandler;
import lion.json.handlers.DateHandler;
import lion.json.handlers.EnumHandler;
import lion.json.handlers.InputStreamHandler;
import lion.json.handlers.MapHandler;
import lion.json.handlers.MethodHandler;
import lion.json.handlers.NumberHandler;
import lion.json.handlers.ObjectHandler;
import lion.json.handlers.StringHandler;

/**
 * @author lion
 * @mail hl_0074@sina.com
 * @date 2011-9-27
 */
public class Json {

	private static Map<String, IJsonHandler> handlers = new HashMap<>();
	private static Log log = LogFactory.getLog(Json.class);

	static {
		handlers.put("Date", new DateHandler());
		handlers.put("String", new StringHandler());
		handlers.put("Number", new NumberHandler());
		handlers.put("Boolean", new BooleanHandler());
		handlers.put("Array", new ArrayHandler());
		handlers.put("Map", new MapHandler());
		handlers.put("Collection", new CollectionHandler());
		handlers.put("Method", new MethodHandler());
		handlers.put("Class", new ClassHandler());
		handlers.put("Object", new ObjectHandler());
		handlers.put("InputStream", new InputStreamHandler());
		handlers.put("byte[]", new ByteArrayHandler());
		handlers.put("Enum", new EnumHandler());
	}

	public static void registHandler(Class<?> clazz, IJsonHandler handler) {

		handlers.put(clazz.getName(), handler);
	}

	public static String toJson(Object o) {

		StringBuilderWriter sw = new StringBuilderWriter(200);
		toJson(o, sw);
		return sw.toString();
	}

	public static void toJson(Object o, Writer writer) {

		if (o == null) {
			try {
				writer.write("null");
			} catch (IOException e) {
				log.error("", e);
			}
			return;
		}

		// 配置处理器
		IJsonHandler handler = handlers.get(o.getClass().getName());
		if (handler == null) {
			handler = handlers.get(o.getClass().getSimpleName());
		}
		// 内置处理器
		if (handler == null) {
			if (o instanceof InputStream) {
				handler = handlers.get("InputStream");
			} else if (o.getClass().isArray()) {
				handler = handlers.get("Array");
			} else if (o instanceof Number) {
				handler = handlers.get("Number");
			} else if (o instanceof Map) {
				handler = handlers.get("Map");
			} else if (o instanceof Collection) {
				handler = handlers.get("Collection");
			} else if (o instanceof CharSequence || o instanceof Character) {
				handler = handlers.get("String");
			} else if (o instanceof Boolean) {
				handler = handlers.get("Boolean");
			} else if (o instanceof Date) {
				handler = handlers.get("Date");
			} else if (o instanceof Method) {
				handler = handlers.get("Method");
			} else if (o instanceof Class) {
				handler = handlers.get("Class");
			} else if (o instanceof Enum) {
				handler = handlers.get("Enum");
			} else {
				handler = handlers.get("Object");
			}
		}
		try {
			handler.handle(o, writer);
		} catch (IOException e) {
			log.error("", e);
		}
	}
}
